﻿using CommunityToolkit.Mvvm.ComponentModel;
using Daq.Models;
using Daq.Services;
using Modbus.Device;
using ScottPlot.Colormaps;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;

namespace Daq.Devices
{
    public class DeviceInfo : ObservableObject
    {
        [JsonPropertyName("model")]
        public string? Model { get; set; }
        [JsonPropertyName("ip")]
        public string? Address { get; set; }
        [JsonPropertyName("netmask")]
        public string? NetMask { get; set; }
        [JsonPropertyName("version")]
        public string? Version { get; set; }
        [JsonPropertyName("sn")]
        public string? SN { get; set; }

        private bool isDefault;
        [JsonIgnore]
        public bool IsDefault
        {
            get { return isDefault; }
            set
            {
                SetProperty(ref isDefault, value);
            }
        }
    }

    internal class DxDaq
	{
        private static readonly TimeSpan searchDeviceTimeout = TimeSpan.FromSeconds(1);

        private static async Task<List<byte[]>> ReceiveDataWithTimeoutAsync(UdpClient client, TimeSpan timeout, CancellationToken cancellationToken)
        {
            int maxPackets = 10;
            List<byte[]> results = [];
            DateTime startTime = DateTime.Now;

            // 循环接收数据包，直到达到最大数量或超时
            for (int i = 0; i < maxPackets; i++)
            {
                // 计算剩余超时时间
                TimeSpan remainingTime = timeout - (DateTime.Now - startTime);
                if (remainingTime <= TimeSpan.Zero)
                {
                    Debug.WriteLine("接收超时，已达到最大等待时间");
                    break;
                }

                try
                {
                    // 串行接收：只启动一个接收任务，等待其完成或超时
                    Task<UdpReceiveResult> receiveTask = client.ReceiveAsync(cancellationToken).AsTask();
                    Task delayTask = Task.Delay(remainingTime, cancellationToken);

                    // 等待接收完成或超时
                    Task completedTask = await Task.WhenAny(receiveTask, delayTask);

                    if (completedTask == receiveTask && receiveTask.IsCompletedSuccessfully)
                    {
                        // 成功接收一个数据包
                        results.Add(receiveTask.Result.Buffer);
                        Debug.WriteLine($"成功接收第{i + 1}/{maxPackets}个数据包，长度: {receiveTask.Result.Buffer.Length}字节");
                        Debug.WriteLine($"来源IP: {receiveTask.Result.RemoteEndPoint.Address}");
                    }
                    else
                    {
                        // 超时或取消
                        //Debug.WriteLine($"第{i + 1}/{maxPackets}个数据包接收超时");
                        break;
                    }
                }
                catch (OperationCanceledException)
                {
                    Debug.WriteLine("接收操作被取消");
                    break;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"接收过程发生错误: {ex.Message}");
                    break;
                }
            }

            Debug.WriteLine($"{client.Client.LocalEndPoint}共接收{results.Count}个数据包");
            foreach (var result in results)
            {
                Debug.WriteLine(Encoding.Default.GetString(result));
            }
            return results;
        }
        
        private static async Task SendBroadcastDataAsync(UdpClient client, IPAddress interfaceAddress)
        {
            IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Broadcast, 50000);
            byte[] data = [0x01, 0x02, 0x04, 0x08];
            await client.SendAsync(data, data.Length, remoteEndpoint);
            Debug.WriteLine($"Sent broadcast data from interface: {interfaceAddress}");
        }


        public static async Task<List<DeviceInfo>> SearchDevices()
        {
            List<string> list = [];
            try
            {
                // 获取所有网络接口
                var interfaces = NetworkInterface.GetAllNetworkInterfaces();
                List<UdpClient> clients = [];
                List<Task<List<byte[]>>> _tasks = [];
                // 遍历所有网络接口并创建UdpClient实例
                foreach (var interfaceItem in interfaces)
                {
                    if (interfaceItem.OperationalStatus == OperationalStatus.Up &&
                        interfaceItem.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                    {
                        var properties = interfaceItem.GetIPProperties();
                        var unicastAddresses = properties.UnicastAddresses;
                        foreach (var address in unicastAddresses)
                        {
                            if (address.Address.AddressFamily == AddressFamily.InterNetwork)
                            {
                                UdpClient client = new UdpClient();
                                clients.Add(client);
                                IPEndPoint localEndpoint = new IPEndPoint(address.Address, 50001);
                                client.Client.Bind(localEndpoint);
                                client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);

                                // 启动接收数据的任务
                                _tasks.Add(ReceiveDataWithTimeoutAsync(client, searchDeviceTimeout, CancellationToken.None));
                                // 发送广播数据
                                for (int i = 0; i < 3; i++)
                                {
                                    await SendBroadcastDataAsync(client, address.Address);
                                    await Task.Delay(100);
                                }
                            }
                        }
                    }
                }


                // 等待所有接收数据的任务完成
                await Task.WhenAll(_tasks);

                foreach (var client in clients)
                {
                    client.Dispose();
                }


                foreach (var task in _tasks)
                {
                    var arrays = task.Result;
                    foreach (var array in arrays)
                    {
                        if (array != null)
                        {
                            string str = Encoding.UTF8.GetString(array);
                            list.Add(str);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error: {ex.Message}");
            }
            List<DeviceInfo> devices = [];
            foreach (string str in list)
            {
                try
                {
                    DeviceInfo? device = JsonSerializer.Deserialize<DeviceInfo>(str);
                    if (device != null && !devices.Any(dev=>dev.SN == device.SN))
                    {
                        devices.Add(device);
                    }
                }
                catch
                {
                }
            }
            return devices;
        }
    }
}
